function Line (world, init_x, init_y, length, init_minx, init_maxx)
    local self = {
        minX = init_minx,
        maxX = init_maxx
    }

    -- create getter functions

    local function getLastVertex()
        local wcx, wcy = self.lastFixture['fixture']:getBody():getWorldCenter()
        return wcx + self.endX, wcy + self.endY
    end
    
    local function getLastY()
        local x,y = getLastVertex()
        return y
    end

    local function setSpeed(s)
        for i,fix in ipairs(self.fixtures) do
            fix['fixture']:getBody():setLinearVelocity(0,s)
        end
        self.speed = s
    end

    local function setBounds(minX, maxX)
        self.minX = minX
        self.maxX = maxX
    end

    local function transformVertices(polydef, xOff, yOff)
        transformed_polydef = {}
        for i,pt in ipairs(polydef) do
            -- odd indices are x's, evens are y's
            if (i%2 == 0) then
                table.insert(transformed_polydef, pt + yOff)
            else
                table.insert(transformed_polydef, pt + xOff)
            end
        end

        return transformed_polydef
    end

    local function getVisibleLineVertices()
        local allVertices = {}
        local wasPreviousVisible = false
        for i,fix in ipairs(self.fixtures) do
            local wcx, wcy = fix['fixture']:getBody():getWorldCenter()
            local transformedVertices = transformVertices(fix['vertices'], wcx - fix['origX'], wcy - fix['origY'])
            local j = 1;
            local totalVerts = #transformedVertices

            while (j <= totalVerts-1) do
                local x,y = transformedVertices[j], transformedVertices[j+1]
                local shouldAdd = true --false
                -- if this point is above the screen, only add to the list if the next point is on the screen
                if (y > SCREEN_HEIGHT/2) then
                    if (totalVerts >= j+3 and transformedVertices[j+3] <= SCREEN_HEIGHT/2) then
                        shouldAdd = true
                    end
                elseif (y < -SCREEN_HEIGHT/2) then
                    if (j-1 > 1 and transformedVertices[j-1] >= -SCREEN_HEIGHT/2) then
                        shouldAdd = true
                    else
                        -- at this point no more vertices will be added. let's short-circuit
                        return allVertices
                    end
                else
                    shouldAdd = true
                end

                if (shouldAdd) then
                    table.insert(allVertices, x)
                    table.insert(allVertices, y)
                end

                j = j+2;
            end
        end

        return allVertices
    end

    -- other functions
    local function destroyAbove(self, aboveY)
        -- go through the list of fixures (segments of the wall). As we do so, save off the previously
        -- visited fixture. We can tell what the previous fixture's end position is because it should
        -- be the same as the next fixtures starting position. So if the current fixture's position
        -- is above the "aboveY" then we destroy the previous fixture and its body since its end
        -- position is above the cutoff and end position is what we care about here.
        local prevFixture = nil
        for i,fix in ipairs(self.fixtures) do
            if (prevFixture) then
                local body = fix['fixture']:getBody()
                local x,y = body:getWorldCenter()
                if (y > aboveY) then
                    prevFixture['fixture']:getBody():destroy()
                    prevFixture['fixture']:destroy()

                    table.remove(self.fixtures, i-1)
                end
            end
            prevFixture = fix
        end

        -- if there's only one fixture or all of the fixtures are above the "aboveY" then
        -- we want to destroy the last fixture and its body as well.
        if (prevFixture and getLastY() > aboveY) then
            local body = prevFixture:getBody()
            body:destroy()
            prevFixture:destroy()

            table.remove(self.fixtures)
        end
    end

    local function createSegment(self, x0, y0, length)
        local polydef = {0,0}
        for i=2,length do
          local x = random(self.minX-x0, self.maxX-x0);
          local y = -(i-1);
          table.insert(polydef, x)
          table.insert(polydef, y)

          if (i == length) then
              self.endX = x
              self.endY = y
          end
        end

        local body = world:addBody(MOAIBox2DBody.KINEMATIC);

        local fix = body:addChain(polydef)
        fix:setDensity(1)
        fix:setFriction(2)
        fix:setFilter(0x01)

        body:resetMassData()
        body:setTransform(x0, y0)

        if (self.fixtures == nil) then self.fixtures = {} end
        local fixture = {
            fixture = fix,
            vertices = transformVertices(polydef, x0, y0),
            origX = x0,
            origY = y0
        };
        table.insert(self.fixtures, fixture)
        self.lastFixture = fixture

        if (self.speed) then
            body:setLinearVelocity(0,self.speed)
        end
    end

    local function onDraw(index, xOff, yOff, xFlip, yFlip)
        MOAIGfxDevice.setPenColor ( 1, 1, 1, 1 )
        MOAIGfxDevice.setPenWidth ( 2 )

        local vertices = getVisibleLineVertices()

        local fanX = SCREEN_WIDTH/2 + 100
        if (self.minX < 0) then fanX = -fanX end
        MOAIDraw.fillFan(fanX, -SCREEN_HEIGHT/2 - 2, fanX, SCREEN_HEIGHT/2 + 2, unpack(vertices))
    end

    local function update()
        destroyAbove(self, SCREEN_HEIGHT/2)

        if (getLastY() > -SCREEN_HEIGHT/2 - 1) then
            local x,y = getLastVertex()
            createSegment(self, x, y, 5)
        end
    end

    -- CONSTRUCTOR
    createSegment(self, init_x, init_y, length)

    -- setup a script deck for drawing the lines of the wall
    local scriptDeck = MOAIScriptDeck.new ()
    if (self.minX < 0) then
        scriptDeck:setRect ( -SCREEN_WIDTH/2, -SCREEN_HEIGHT/2, self.maxX, SCREEN_HEIGHT/2 )
    else
        scriptDeck:setRect ( self.minX, -SCREEN_HEIGHT/2, SCREEN_WIDTH/2, SCREEN_HEIGHT/2 )
    end
    scriptDeck:setDrawCallback ( onDraw )

    -- add the script deck to the layer
    local prop = MOAIProp2D.new ()
    prop:setDeck ( scriptDeck )
    layer:insertProp ( prop )

    -- make some functions available publicly
    return {
        getLastVertex = getLastVertex,
        getLastY      = getLastY,
        setSpeed      = setSpeed,
        update        = update,
        setBounds     = setBounds,
    }
end